package com.uxsino.simo.indicator.retractor;

import com.uxsino.commons.utils.config.ConfigProp;
import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryContext;
import com.uxsino.simo.query.QueryTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.Map.Entry;

public class CSVListRetractor3 extends CSVListRetractor {
    private static final Logger logger = LoggerFactory.getLogger(CSVListRetractor3.class);

    @ConfigProp(name = "col_id_replace_reg", trim = false, required = true)
    public String colIdReplaceReg;

    // include like parent name
    // separated by ,
    @ConfigProp(name = "block_common_col_ids", trim = false)
    public String blockCommonColIds;

    // method supported: index
    @ConfigProp(name = "col_id_replace_method")
    public String colIdReplaceMethod;

    @ConfigProp(name = "col_id_replace_ref")
    public String colIdReplaceRef;

    @ConfigProp(name = "col_split_symbol", trim = false, required = true)
    public String colSplitSymbol;

    public CSVListRetractor3() {
        super();
        colIdReplaceReg = "";
        blockCommonColIds = "";
        colIdReplaceMethod = "index";
        colIdReplaceRef = "";
        colSplitSymbol = "=";
    }

    @Override
    public Object doRetract(EntityInfo entity, QueryContext ctxt, QueryTemplate qt, Object obj) {
        String buf = getTable((String) obj);
        String[] lines = getLines(buf);
        List<Map<String, Object>> records = new ArrayList<>();

        Set<String> blockCommonFieldColIds = new HashSet<>(Arrays.asList(blockCommonColIds.split(",")));
        Map<String, ColumnEntry> diffFieldColIdsMap = new HashMap<>();
        Map<String, ColumnEntry> commonFieldColIdsMap = new HashMap<>();

        for (ColumnEntry entry : columnEntries) {
            String colId = entry.index;
            if (blockCommonFieldColIds.contains(colId)) {
                commonFieldColIdsMap.put(colId, entry);
            } else {
                diffFieldColIdsMap.put(colId, entry);
            }
        }

        for (String line : lines) {
            String[] cols = splitRow(line);
            List<String> replacements = new ArrayList<>();
            Map<String, String> colValueMap = new HashMap<>();
            getReplacementsAndStoreVals(cols, replacements, colValueMap);

            List<Map<String, Object>> diffMapList = new ArrayList<>();
            for (int i = 0; i < replacements.size(); i++) {
                diffMapList.add(new HashMap<String, Object>());
            }
            Map<String, Object> commonMap = new HashMap<>();

            for (String commonId : blockCommonFieldColIds) {
                if (colValueMap.containsKey(commonId)) {
                    ColumnEntry entry = commonFieldColIdsMap.get(commonId);
                    commonMap.put(entry.field.getName(), entry.retractor.retract(entity, ctxt, qt, colValueMap.get(commonId)));
                }
            }
            for (Entry<String, ColumnEntry> entry : diffFieldColIdsMap.entrySet()) {
                String keyPattern = entry.getKey();
                ColumnEntry columnEntry = entry.getValue();
                for (int i = 0; i < replacements.size(); i++) {
                    String key = keyPattern.replaceAll(colIdReplaceReg, replacements.get(i));
                    if (colValueMap.containsKey(key)) {
                        diffMapList.get(i).put(columnEntry.field.getName(),
                            columnEntry.retractor.retract(entity, ctxt, qt, colValueMap.get(key)));
                    }
                }
            }

            boolean allDiffMapEmpty = true;
            for (Map<String, Object> diffMap : diffMapList) {
                if (!diffMap.isEmpty()) {
                    allDiffMapEmpty = false;
                    diffMap.putAll(commonMap);
                    records.add(diffMap);
                }
            }
            if (allDiffMapEmpty) {
                records.add(commonMap);
            }
        }
        return records;

    }

    private void getReplacementsAndStoreVals(String[] cols, List<String> replacements,
        Map<String, String> colValueMap) {
        for (String col : cols) {
            String[] arr = col.split(colSplitSymbol);
            if (arr == null || arr.length != 2)
                continue;
            String colTitle = arr[0].trim();
            String colValue = arr[1].trim();
            if (colTitle.equals(colIdReplaceRef)) {
                getReplacementValues(colValue, replacements);
            } else {
                colValueMap.put(colTitle, colValue);
            }
        }
    }

    private void getReplacementValues(String values, List<String> replacements) {
        if (colIdReplaceMethod.equals("index")) {
            int size = Integer.parseInt(values);
            if (size < 1) {
                logger.error("index replacement size < 1, size:{}", size);
                return;
            }
            for (int i = 0; i < size; i++) {
                replacements.add(String.valueOf(i));
            }
        } else {
            logger.error("unsupported replacement method {}", colIdReplaceMethod);
        }
    }

}
